package com.aizuda.boot.modules.business.feishu;

import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.service.ContractFieldService;
import com.aizuda.boot.modules.business.contract.service.ContractService;
import com.aizuda.boot.modules.business.feishu.domain.AtUsersDTO;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationInstanceMapper;
import com.aizuda.boot.modules.common.constant.enums.SystemFieldsEnum;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.bpm.engine.TaskReminder;
import com.aizuda.bpm.engine.assist.DateUtils;
import com.aizuda.bpm.engine.core.FlowLongContext;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.entity.FlwTaskActor;
import com.aizuda.bpm.mybatisplus.mapper.FlwTaskActorMapper;
import com.aizuda.bpm.spring.autoconfigure.FlowLongProperties;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Author sangyirong
 * @ClassName FeiShuTaskReminder
 * @Version 1.0
 * @Date 2025/7/28 13:46
 */
@Slf4j
@Component
@EnableScheduling
public class FeiShuTaskReminder implements TaskReminder {

    @Resource
    private FlwTaskActorMapper flwTaskActorMapper;

    @Resource
    private FeishuBot feishuBot;

    @Resource
    private FlowLongProperties flowLongProperties;

    @Resource
    private ContractService contractService;

    @Resource
    private ContractNegotiationInstanceMapper negotiationInstanceMapper;

    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;

    @Resource
    private ContractFieldService contractFieldService;

    @Resource
    private ISysUserService sysUserService;

    @Override
    public Date remind(FlowLongContext context, Long instanceId, FlwTask currentTask) {
        // 判空处理
        if (flowLongProperties == null || flowLongProperties.getRemind() == null) {
            log.warn("FlowLongProperties或remind配置为空，跳过提醒，实例ID: {}, 任务ID: {}",
                    instanceId, currentTask.getId());
            return null;
        }

        Long taskId = currentTask.getId();
        List<Long> list = flwTaskActorMapper.selectList(Wrappers.<FlwTaskActor>lambdaQuery()
                        .eq(FlwTaskActor::getTaskId, taskId)).stream()
                .map(FlwTaskActor::getActorId).map(Long::parseLong).toList();

        // 构建提醒消息
        AtUsersDTO atUsersDTO = buildReminderMessage(list, currentTask);

        // 发送提醒
        feishuBot.atUsers(atUsersDTO);

        // 计算下次提醒时间
        Date nextReminderTime = calculateNextReminderTime();

        log.info("进行了任务提醒，实例ID: {}, 任务ID: {}, 预计下次提醒时间: {}",
                instanceId, currentTask.getId(), nextReminderTime);

        return nextReminderTime;
    }

    /**
     * 构建提醒消息
     */
    private AtUsersDTO buildReminderMessage(List<Long> userIds, FlwTask currentTask) {
        AtUsersDTO atUsersDTO = new AtUsersDTO();
        atUsersDTO.setUserIds(userIds);

        // 使用配置的标题
        atUsersDTO.setTitle(flowLongProperties.getRemind().getMessage().getTitle());

        // 构建消息内容，替换占位符
        String content = buildMessageContent(currentTask);
        atUsersDTO.setContent(content);

        // 使用配置的业务类型
        atUsersDTO.setBusinessType(flowLongProperties.getRemind().getMessage().getBusinessType());

        return atUsersDTO;
    }

    /**
     * 构建消息内容，支持占位符替换
     */
    private String buildMessageContent(FlwTask currentTask) {
        // 判空处理
        if (flowLongProperties == null || flowLongProperties.getRemind() == null
                || flowLongProperties.getRemind().getMessage() == null) {
            log.warn("FlowLongProperties配置为空，使用默认消息内容");
            return "您有待处理的任务，请及时处理";
        }

        String contentTemplate = flowLongProperties.getRemind().getMessage().getContentTemplate();
        if (contentTemplate == null || contentTemplate.isEmpty()) {
            log.warn("消息内容模板为空，使用默认消息内容");
            return "您有待处理的任务，请及时处理";
        }

        // 计算任务超时时间
        Integer timeoutHours = calculateTimeoutHours(currentTask);
        Long instanceId = currentTask.getInstanceId();
        String flowType;
        int contractId;
        try {
            ContractEntity contract = contractService.getOne(Wrappers.<ContractEntity>lambdaQuery()
                    .eq(ContractEntity::getApprovalInstanceId, instanceId)
                    .last("limit 1"));
            if (null != contract) {
                flowType = "合同审批";
                contractId = contract.getId();
            } else {
                ContractNegotiationInstanceEntity instance = negotiationInstanceMapper.selectOne(Wrappers.<ContractNegotiationInstanceEntity>lambdaQuery()
                        .eq(ContractNegotiationInstanceEntity::getProcessInstanceId, instanceId)
                        .last("limit 1"));
                flowType = "流程审批";
                contractId = instance.getContractId();
            }

            String contractName = getFieldValue(contractId, SystemFieldsEnum.CONTRACT_NAME.getCode());
            String applyPeople = getFieldValue(contractId, SystemFieldsEnum.APPLY_PEOPLE.getCode());

            SysUser user = sysUserService.getById(applyPeople);


            // 替换占位符
            return contentTemplate.replace("{timeoutHours}", timeoutHours.toString())
                    .replace("{nodeName}", currentTask.getTaskName())
                    .replace("{sponsor}", user.getNickName())
                    .replace("{flowType}", flowType)
                    .replace("{contractName}", contractName);
        } catch (Exception e) {
            log.error("构建消息内容失败", e);
            return "您有待处理的任务，请及时处理";
        }


    }

    private String getFieldValue(Integer contractId, String fieldCode) {
        ContractFieldEntity field = contractFieldService.getOne(Wrappers.<ContractFieldEntity>lambdaQuery()
                .eq(ContractFieldEntity::getCode, fieldCode)
                .select(ContractFieldEntity::getId)
                .last("limit 1"));
        ContractFieldValueEntity fieldValue = contractFieldValueMapper.selectOne(Wrappers.<ContractFieldValueEntity>lambdaQuery()
                .eq(ContractFieldValueEntity::getContractId, contractId)
                .eq(ContractFieldValueEntity::getFieldId, field.getId())
                .last("limit 1"));
        return fieldValue.getFieldValue();
    }

    /**
     * 计算任务超时时间（小时）
     */
    private Integer calculateTimeoutHours(FlwTask currentTask) {
        // 判空处理
        if (flowLongProperties == null || flowLongProperties.getRemind() == null
                || flowLongProperties.getRemind().getTimeout() == null) {
            log.warn("FlowLongProperties超时配置为空，使用默认超时时间1小时");
            return 24;
        }

        if (flowLongProperties.getRemind().getTimeout().getEnableDynamicTimeout()) {
            // 动态计算：从任务创建时间到现在的小时数
            if (currentTask.getCreateTime() != null) {
                Date createTime = currentTask.getCreateTime();
                Date date = new Date();
                long hours = DateUtils.calculateDateDifference(createTime, date) / 1000 / 60 / 60;
                return Math.max(1, (int) hours); // 至少1小时
            }
        }

        // 使用配置的固定超时时间
        Integer timeoutHours = flowLongProperties.getRemind().getTimeout().getTimeoutHours();
        return timeoutHours != null ? timeoutHours : 24; // 默认24小时
    }

    /**
     * 计算下次提醒时间
     */
    private Date calculateNextReminderTime() {
        // 判空处理
        if (flowLongProperties == null || flowLongProperties.getRemind() == null
                || flowLongProperties.getRemind().getTiming() == null) {
            log.warn("FlowLongProperties时间配置为空，使用默认间隔14400秒");
            return DateUtils.toDate(DateUtils.now().plusSeconds(4 * 60 * 60L));
        }

        Long intervalSeconds = flowLongProperties.getRemind().getTiming().getNextReminderIntervalSeconds();
        if (intervalSeconds == null || intervalSeconds <= 0) {
            log.warn("提醒间隔配置无效，使用默认间隔14400秒");
            intervalSeconds = 4 * 60 * 60L;
        }

        Date nextTime = DateUtils.toDate(DateUtils.now().plusSeconds(intervalSeconds));
        return adjustToWorkingTIme(nextTime);

    }

    private Date adjustToWorkingTIme(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        // 调整到工作日
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == Calendar.SATURDAY) {
            // 周六调整到下周一
            cal.add(Calendar.DAY_OF_MONTH, 2);
        } else if (dayOfWeek == Calendar.SUNDAY) {
            // 周日调整到下周一
            cal.add(Calendar.DAY_OF_MONTH, 1);
        }

        // 调整到工作时间（9:00-17:00）
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (hour < 9) {
            // 早于9点，调整到9点
            cal.set(Calendar.HOUR_OF_DAY, 9);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
        } else if (hour >= 17) {
            // 晚于17点，调整到下一个工作日的9点
            cal.add(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.HOUR_OF_DAY, 9);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);

            // 再次检查是否为工作日
            dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
            if (dayOfWeek == Calendar.SATURDAY) {
                cal.add(Calendar.DAY_OF_MONTH, 2);
            } else if (dayOfWeek == Calendar.SUNDAY) {
                cal.add(Calendar.DAY_OF_MONTH, 1);
            }
        }

        return cal.getTime();
    }
}
